package SubServer;
import java.io.Serializable;
import java.rmi.RemoteException;
import java.rmi.server.UnicastRemoteObject;
import java.util.HashMap;
import java.util.Vector;

import javax.rmi.ssl.SslRMIClientSocketFactory;
import javax.rmi.ssl.SslRMIServerSocketFactory;

import General.ClientEventInterface;
import General.Product;
import General.QuoteInterface;
import General.ShipQuoterServiceInterface;
import General.ShipmentInterface;

public class ShipQuoterService extends UnicastRemoteObject implements ShipQuoterServiceInterface {
	
	private static final long serialVersionUID = 1L;
	private Vector<Shipment> fPending;
	private Vector<Shipment> fFinished;
	private HashMap<Integer, Integer> fRates;
	private int fShipmentNr;
	
	public ShipQuoterService() throws RemoteException {
		super(0, new SslRMIClientSocketFactory(), new SslRMIServerSocketFactory(null, null, true));
		fPending = new Vector<Shipment>();
		fFinished = new Vector<Shipment>();
		fRates = new HashMap<Integer, Integer>();
		fRates.put(Product.GROUND, 10);
		fRates.put(Product.AIR, 30);
		fRates.put(Product.AIR_PRIORITY, 100);
		fShipmentNr = 1;
	}
	
	public QuoteInterface quote(Product product) throws RemoteException {
		System.out.println("[SUBSERVER] Quote calculation started for product with id " + product.getId());
		return new Quote(product.getWeight() * 10 + fRates.get(product.getfShippingType()), "EUR");
	}

	public boolean requestForShipping(Product product, ClientEventInterface clientNotificator) throws RemoteException {
		System.out.println("[SUBSERVER] Request for shipping of product with id " + product.getId() + " received");
		Shipment shipment = new Shipment(product, (Quote) this.quote(product), clientNotificator, Product.REQUESTED, fShipmentNr);
		fShipmentNr++;
		fPending.add(shipment);
		ShipmentSimulation shipmentSim = new ShipmentSimulation(this, shipment);
		shipmentSim.start();
		return true;
	}

	public int getState(int productId) throws RemoteException {
		for (int i = 0; i < fPending.size(); i++) {
			if (fPending.get(i).getProduct().getId() == productId) {
				return fPending.get(i).getState();
			}
		}
		
		for (int i = 0; i < fFinished.size(); i++) {
			if (fFinished.get(i).getProduct().getId() == productId) {
				return fFinished.get(i).getState();
			}
		}
		return 0;
	}

	public void changeRate(int shippingType, int rate) throws RemoteException {
		fRates.remove(shippingType);
		fRates.put(shippingType, rate);
		System.out.println("[SUBSERVER] Rate for shipment type '" + Product.getShippingTimeName(shippingType) + "' changed to " + rate + " EUR");
	}
	
	public ShipmentInterface getPendingShipment(int shipmentNr) throws RemoteException {
		if (shipmentNr > fPending.size()) {
			return null;
		}
		return fPending.elementAt(shipmentNr-1);
	}
	
	public ShipmentInterface getHistoryShipment(int shipmentNr) throws RemoteException {
		if (shipmentNr > fFinished.size()) {
			return null;
		}
		return fFinished.elementAt(shipmentNr-1);
	}
	
	public void changeToFinished(Shipment shipment) {
		// Add shipment to finished shipments
		fFinished.add(shipment);
		
		// Remove shipment from pending shipments
		for (int i = 0; i < fPending.size(); i++) {
			if (fPending.get(i).getProduct().getId() == shipment.getProduct().getId()) {
				fPending.remove(i);
			}
		}
		
	}
}
